package com.yunyao.web.utils;

import com.alibaba.fastjson2.JSONObject;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectResult;
import com.yunyao.common.constant.enums.DataDeletedStatus;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.SpringContextUtils;
import com.yunyao.framework.dto.file.FileInfoDto;
import com.yunyao.framework.service.system.OssService;
import com.yunyao.framework.vo.OssVo;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.util.Date;

@Data
@Slf4j
@Component
public class AliOssUtil {
    @Autowired
    private static OssService ossService;

    private static String endpoint;
    private static String accessKeyId;
    private static String accessKeySecret;
    private static String bucketName;
    private static String internalEndpoint;

    private static OSS ossClient;

    /**
     * 初始化，从ossService取出数据，构建
     */
    public AliOssUtil() {
    }

    /**
     * 检查ossClient 是否为空
     */
    public static Boolean checkOssClient() {
        try {
            if (ossClient == null) {
                if (ossService == null) {
                    ossService = SpringContextUtils.getBean(OssService.class);
                }
                OssVo ossVo = ossService.getOssConfigByCode("ali");
                endpoint = ossVo.getEndpoint();
                accessKeyId = ossVo.getAccessKey();
                accessKeySecret = ossVo.getSecretKey();
                bucketName = ossVo.getBucketName();
                internalEndpoint = ossVo.getInternalEndpoint();
                ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            }
            return true;
        }catch (Exception e) {
            log.error("ossClient初始化失败");
            return false;
        }
    }

    /**
     * 文件上传
     *
     * @param bytes
     * @param objectName
     * @return
     */
    public static FileInfoDto upload(byte[] bytes, String objectName, String fileType) {
        JSONObject fileJson = new JSONObject();
        FileInfoDto fileInfoDto = new FileInfoDto();
        // 创建OSSClient实例。
        if (!checkOssClient()){
            fileJson.put("error","ossClient初始化失败");
            return null;
        }
        try {
            fileJson.put("name", objectName);

            String lastFix = "";
            String firstName = "";
            if (objectName.contains(".")){
//                lastFix = objectName.split(".")[1];
                lastFix = objectName.substring(objectName.lastIndexOf(".")+1);
                firstName = objectName.substring(0,objectName.lastIndexOf("."));
            }
            String todayPath = ConvertUtil.getFormatDate(new Date(),false,"yyyyMMdd")+"/"+System.currentTimeMillis();
            String pathName = "upload"+"/"+todayPath+"/"+firstName+"."+lastFix;

            StringBuilder fileUrl = new StringBuilder(internalEndpoint);
            fileUrl.append("/")
                    .append(pathName);
            fileJson.put("url", fileUrl);
            fileJson.put("uuidObjectName", pathName);

            fileInfoDto.setOriginalName(objectName);
            fileInfoDto.setLink(fileUrl.toString());
            fileInfoDto.setName(pathName);
            fileInfoDto.setBucketName(bucketName);
            fileInfoDto.setInternalDomain(internalEndpoint);
            fileInfoDto.setDomain(internalEndpoint);
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(bucketName, pathName, new ByteArrayInputStream(bytes));

            fileInfoDto.setSource("ali");
            fileInfoDto.setUploadId(result.getETag());
            fileInfoDto.setExtension(lastFix);
            fileInfoDto.setUploadStatus("4");
            fileInfoDto.setStatus(1);
            fileInfoDto.setIsDeleted(DataDeletedStatus.NO.getType());
            System.out.println(JSONObject.toJSONString(result));
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message:" + oe.getErrorMessage());
            log.error("Error Code:" + oe.getErrorCode());
            log.error("Request ID:" + oe.getRequestId());
            log.error("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
                ossClient = null;
            }
        }

        //文件访问路径规则 [{"name":"document1_00.png","url":
        // "https://project-ycerp.oss-cn-hangzhou.aliyuncs.com/upload/20230925/ce1b7dae4e3ae84b62fe43b487b34f55.png"}]
        log.info("文件上传到:{}", fileJson.toJSONString());

        return fileInfoDto;
    }

    public static Boolean delete(String uuidObjectName) {
        if (!checkOssClient()){
            return false;
        }
        try {
            ossClient.deleteObject(bucketName,uuidObjectName);
            return true;
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message:" + oe.getErrorMessage());
            log.error("Error Code:" + oe.getErrorCode());
            log.error("Request ID:" + oe.getRequestId());
            log.error("Host ID:" + oe.getHostId());
            return false;
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message:" + ce.getMessage());
            return false;
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
                ossClient = null;
            }
        }
    }
}
